package com.chuanqi.admin.shiro;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.chuanqi.admin.domain.PermittedRecordModel;
import com.chuanqi.admin.domain.User;
import com.chuanqi.admin.service.PermittedItemResourceIdService;
import com.chuanqi.admin.service.UserService;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * <p>User: Xiong Xianquan
 * <p>Date: 14-1-28
 * <p>Version: 1.0
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    
    @Autowired
    private PermittedItemResourceIdService permittedItemResourceIdService;
    
    /**
	 * 认证回调函数,登录时调用.
	 */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
    	UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
    	String username = token.getUsername();
    	System.out.println("--UserRealm.doGetAuthenticationInfo--"+username);
        //String username = (String)token.getPrincipal();

        User user = userService.findByUsername(username);

        if(user == null) {
            throw new UnknownAccountException();//没找到帐号
        }

        if(Boolean.TRUE.equals(user.getLocked())) {
            throw new LockedAccountException(); //帐号锁定
        }

        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，如果觉得人家的不好可以自定义实现
        /*SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getUsername(), //用户名
                user.getPassword(), //密码
                ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );*/       
        
        List<PermittedRecordModel> permittedRecordModels = permittedItemResourceIdService.getPermittedItemResourceIdByUserId(user.getId());        	
    	List<Long> permittedItemIds = new ArrayList<Long>();
    	for(PermittedRecordModel entity : permittedRecordModels){
    		permittedItemIds.add(entity.getRecordId());
    	}
    
    	SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
        		new ShiroUser(user.getId(), user.getUsername(), permittedItemIds), //用户ShiroUser
                user.getPassword(), //密码
                //ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
                ByteSource.Util.bytes(user.getSalt()), 
                getName()  //realm name
                //springside4
                //user.getPassword(), 
                //ByteSource.Util.bytes(salt), 
                //getName());
        );        
        return authenticationInfo;
        
        
    }
    
    /**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //String username = (String)principals.getPrimaryPrincipal();
    	ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
    	System.out.println("--UserRealm.doGetAuthorizationInfo--"+shiroUser.getUsername());
    	
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //authorizationInfo.setRoles(userService.findRoles(username));
        //authorizationInfo.setStringPermissions(userService.findPermissions(username));
        
        authorizationInfo.setRoles(userService.findRoles(shiroUser.getUsername()));
        authorizationInfo.setStringPermissions(userService.findPermissions(shiroUser.getUsername()));
        
        
        return authorizationInfo;
    }

    /*@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
		User user = accountService.findUserByLoginName(shiroUser.loginName);
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addRoles(user.getRoleList());
		return info;
	}*/
    

    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }
    
    /**
	 * 自定义Authentication对象，使得Subject除了携带用户的登录名外还可以携带更多信息.
	 */
	public static class ShiroUser implements Serializable {
		private static final long serialVersionUID = 1L;
		public Long id;
		public String username;
		public List<Long> itemIds;		

		public Long getId() {
			return id;
		}
		
		public String getUsername() {
			return username;
		}	
		
		public List<Long> getItemIds() {
			return itemIds;
		}
		
		/**
		 * 本函数输出将作为默认的<shiro:principal/>输出.
		 */
		@Override
		public String toString() {
			return username;
		}

		public ShiroUser(Long id, String username, List<Long> itemIds) {
			this.id = id;
			this.username = username;	
			this.itemIds = itemIds;
		}		
	}

}
